"use strict";
//dmm平台相关
const crypto = require('crypto')
const request = require('request')
const querystring = require('querystring');
//const url = 'http://sbx-osapi.dmm.com/social_sp/rest/'

const Platform = {
    0:{
        "sandbox":"http://sbx-osapi.dmm.com/social_sp/rest/",
        "production":"https://osapi.dmm.com/social_sp/rest/",
    },
    1:{
        "sandbox":"http://sbx-osapi.dmm.com/social_pc/rest/",
        "production":"https://osapi.dmm.com/social_pc/rest/",
    }
}


exports.format = {
    "id":'dmm',
    "name":"DMM平台",
    "fields":{
        "dmm" :{'type':'int','val':0,'name':"平台","option":{"0":"移动端","1":"PC端"}  },
        "key" :{'type':'string','val':'','name':"consumerKey"},
        "secret" :{'type':'string','val':'','name':"consumerSecret"},
        "keyR" :{'type':'string','val':'','name':"consumerKeyR"},
        "secretR" :{'type':'string','val':'','name':"consumerSecretR"},


        //"pageurl" :{'type':'string','val':'','name':"finishPageUrl[移动端]"},
        //"servurl" :{'type':'string','val':'','name':"DMM安全验证服务器地址(URL/social/rest/)"},
    }
}



//==========================================入口=================================================//
exports.login = function(){
    if(!this.opensdk.setting || !this.opensdk.setting.key || !this.opensdk.setting.secret ){
        return this.error("opensdk.setting error");
    }
    let dmm = this.opensdk.setting.dmm || 0;
    if(!Platform[dmm]){
        return this.error("opensdk.setting dmm not exist",dmm);
    }
    return Platform[dmm]['login'].apply(this,arguments);
}
exports.userinfo = function(){
    if(!this.opensdk.setting || !this.opensdk.setting.key || !this.opensdk.setting.secret ){
        return this.error("opensdk.setting error");
    }
    let dmm = this.opensdk.setting.dmm || 0;
    if(!Platform[dmm] ){
        return this.error("opensdk.setting dmm not exist",dmm);
    }
    if( !Platform[dmm]['userinfo'] ){
        return this.error("Platform.userinfo exist",dmm);
    }
    return Platform[dmm]['userinfo'].apply(this,arguments);
}
exports.orderCreate = function(){
    if(!this.opensdk.setting || !this.opensdk.setting.key || !this.opensdk.setting.secret ){
        return this.error("opensdk.setting error");
    }
    let dmm = this.opensdk.setting.dmm || 0;
    if(!Platform[dmm]){
        return this.error("opensdk.setting dmm not exist",dmm);
    }
    return Platform[dmm]['orderCreate'].apply(this,arguments);
}
exports.orderNotify = function(){
    if(!this.opensdk.setting || !this.opensdk.setting.key || !this.opensdk.setting.secret ){
        return this.error("opensdk.setting error");
    }
    let dmm = this.opensdk.setting.dmm || 0;
    if(!Platform[dmm]){
        return this.error("opensdk.setting dmm not exist",dmm);
    }
    return Platform[dmm]['orderNotify'].apply(this,arguments);
}
exports.orderResult = function(){
    if(!this.opensdk.setting || !this.opensdk.setting.key || !this.opensdk.setting.secret ){
        return this.error("opensdk.setting error");
    }
    let dmm = this.opensdk.setting.dmm || 0;
    if(!Platform[dmm]){
        return this.error("opensdk.setting dmm not exist",dmm);
    }
    return Platform[dmm]['orderResult'].apply(this,arguments);
}


//==========================================移动=================================================//
Platform[0]['login'] = function() {
    let dmmParams = this.get('dmmJson', 'json');
    if(!dmmParams){
        return this.error("dmmParams error");
    }
    return Promise.resolve().then(()=>{
        // return mobile_request.call(this,dmmParams, 'GET',  'people/@me/@self', {  'fields': 'id,userType' });  // yyb
        return mobile_request.call(this,dmmParams, 'GET',  'people/@me/@self', {  'fields': 'id' });
    }).then(ret=>{
        if(!ret || !ret['entry'] || !ret['entry']['id'] ){
            return this.error('dmmRequest error',ret||'unknown');
        }
        else{
            return {'openid':ret['entry']['id'],'userinfo':ret['entry']};
        }
    })
}

Platform[0]['userinfo'] = function() {
    let dmmParams = this.get('dmmJson', 'json');
    if(!dmmParams){
        return this.error("dmmParams error");
    }
    let fields = this.get('fields', 'string') || 'id,userType,nickname';
    return Promise.resolve().then(()=>{
        return mobile_request.call(this,dmmParams, 'GET',  'people/@me/@self', {  'fields': fields });
    }).then(ret=>{
        if(!ret || !ret['entry'] ){
            return this.error('dmmRequest error',ret||'unknown');
        }
        else{
            return ret['entry'];
        }
    })
}

Platform[0]['orderCreate'] = function(config,notify) {


    let _finishPageUrl  = this.get("finishPageUrl","string");
    if(!_finishPageUrl){
        _finishPageUrl=this.opensdk.setting.pageurl;
    }

    let _env="dmm_live";
    if(this.opensdk.status===0){
        _env="dmm_sandbox";
    }




    _finishPageUrl=`${_finishPageUrl}?platform=sp&env=${_env}&provider=dmm`; 





    //console.log(_finishPageUrl);

    if(!this.opensdk.setting || !this.opensdk.setting.key || !this.opensdk.setting.secret ){
        return this.error("opensdk.setting error");
    }
    //let pageurl = this.get('pageurl', 'string');
    let dmmParams = this.get('dmmJson', 'json');
    if(!dmmParams){
        return this.error("dmmParams error");
    }
    config['attach']=config['attach']+'|'+this.opensdk.setting.key;
    let notify_callback = [notify,config['attach']].join('/')
    let params = {
        "callbackUrl": notify_callback,
        //"finishPageUrl": [notify_callback,this.opensdk.setting.key].join('|'),
        "finishPageUrl":_finishPageUrl,
        "message": this.get("message","string"),
        "paymentItems": [
            {
                "itemId": String(config['id']),
                "itemName": this.get("name","string"),
                "unitPrice": String(config["rmb"]),
                "quantity": "1",
                "imageUrl": this.get("image","string"),
                "description": this.get("description","string")
            }
        ]
    }
    return mobile_request.call(this,dmmParams, 'POST', 'payment/@me/@self/@app', {}, params)
}

/**
 * @name orderNotify
 * 支付回调
 */

Platform[0]['orderNotify'] = function(){
    //判断回调来源
    let attach = this.get("attach","string");
    let paymentId = this.get("paymentId","string");
    if(!attach){
        return this.error("attach empty");
    }
    if(!paymentId){
        return this.error("paymentId empty");
    } 
    let arr = attach.split('|');
    if( !arr[3] || ((arr[3] !== this.opensdk.setting.key)&&(arr[3] !== this.opensdk.setting.keyR))){
        return this.error('orderNotify',attach);
    }
    else {
        return mobile_notify.call(this,attach ,paymentId);
    }
}

/**
 * @name orderResult
 * 回调信息
 */

Platform[0]['orderResult'] = function(err,ret){
    // if(err || err !=='success'){
    //     return this.error(err);
    // }
    //
    // let attach = this.get("attach","string");
    // let arr = attach.split('|');
    // if( !arr[3] || arr[3] !== this.opensdk.setting.key ){
    //     return this.success(ret);
    // }
    if(err){
        this.status = 500;
        return this.error('err',err);
    }else{
        //发货成功
        return 'OK';
    }
    // let pageurl = this.opensdk.setting.pageurl||'';
    // let dmmParams = this.req.query;
    // let url = [pageurl,querystring.stringify(dmmParams) ].join('?');
    // this.output = 'redirect';
    // console.log(url);
    // return url;
}

//移动游戏发货
function mobile_notify(attach ,paymentId) {
    //发货
    //let status = this.get("status","int");
    let dmmParams = this.req.query;
    if(!dmmParams){
        return this.error("dmmParams empty");
    }

    if(dmmParams.status==2){
        //订单成功，发货
        return {"attach":attach,"orderid":paymentId};
    }
    else{
        return this.error('dmm notify error');
    }

    // return Promise.resolve().then(()=>{
    //     return mobile_request.call(this,dmmParams, 'GET',   `payment/${dmmParams.opensocial_viewer_id}/@self/@app/${paymentId}`, {}, null);
    // }).then(ret=>{
    //     console.log(ret);
    //     if(!ret || !ret['entry']){
    //                console.log("A2");
    //         return this.error('dmm notify error',ret);
    //     }
    //     if(ret['entry']['status'] ==2){
    //         return {"attach":attach,"orderid":paymentId};
    //     }
    //     else{
    //                console.log("A3");
    //         return this.error("success",`orderNotify status error:${paymentId}`);
    //     }
    // })
}
//移动端平台交互
function mobile_request(p, httpMethod, apiUrl, queryParam = {}, params) {
    if (!p) {
        return Promise.resolve() 
    }
    apiUrl = (this.opensdk.status > 0 ? Platform[0].production : Platform[0].sandbox) + apiUrl;
    let _final_key=this.opensdk.setting.keyR;
    let _final_sec=this.opensdk.setting.secretR;
    if(p.oauth_consumer_key==this.opensdk.setting.key){
        //普通版
        _final_key=this.opensdk.setting.key;
        _final_sec=this.opensdk.setting.secret;
    }
    let time = Date.now();
    let dmmParam = {
        oauth_consumer_key: encodeURIComponent(_final_key), //consumerKey,
        oauth_nonce: time.toString(32),
        oauth_timestamp: Math.floor(time / 1000),
        oauth_token: p.oauth_token,
        oauth_signature_method: p.oauth_signature_method,
        oauth_version: p.oauth_version,
        xoauth_requestor_id: p.opensocial_viewer_id
    }

    let oauthTokenSecret = p.oauth_token_secret

    let queryArr = []
    for (let k in queryParam) {
        queryArr.push(`${k}=${queryParam[k]}`)
    }

    let authDmmParam = JSON.parse(JSON.stringify(dmmParam))
    authDmmParam.oauth_signature = createSign.call(this,httpMethod, apiUrl, queryParam, dmmParam, oauthTokenSecret,_final_sec)

    apiUrl  = queryArr.length > 0 ? apiUrl + "?" + queryArr.join('&') : apiUrl

    let options = {
        method: httpMethod,
        url: apiUrl,
        headers: {
            "Content-Type": 'application/json',
            'Authorization': createAuthorization(authDmmParam)
        }
    }
    if(params) {
        options.body = JSON.stringify(params)
    }

    //console.log(options)

    return new Promise((resolve, reject) => {
        request(options, function (err, res, body) {
            if (err) {
                reject(err)
            }
            else{
                let json = JSON.tryParse(body)||body;
                resolve(json);
            }
        })
    })

}


//==========================================PC=================================================//
Platform[1]['login'] = function() {
    let openid = this.get('openid', 'string');
    if(!openid){
        return this.error("openid empty");
    }
    return openid;
}
//客户端自己验证
Platform[1]['orderCreate'] = function(config,notify) {
    return config;
}

/**
 * @name orderNotify
 * 支付回调
 */

Platform[1]['orderNotify'] = function(){
    if(this.req.method === 'POST'){
        //this.library("debug",'orderNotify POST',this.req.body);
        return PC_Notify_Submit.call(this);
    }
    else{
        //this.library("debug",'orderNotify POST',this.req.query);
        return PC_Notify_Goods.call(this);
    }
}

/**
 * @name orderResult
 * 回调信息
 */

Platform[1]['orderResult'] = function(err,ret){
    this.output = 'application/json';
    if(err && err['err']!=='success' ){
        this.status = 500;
        this.library("debug",err)
        return this.error(err);
    }
    let data = {"response_code":"OK"};
    if(ret && ret['orderid']){
        data['payment_id'] = ret['orderid'];
    }
    return data;
}

//PC端订单确认
async function PC_Notify_Submit() {
    let ITEMS = this.get("ITEMS","json");
    let PAYMENT_ID = this.get("PAYMENT_ID","string");
    if(!Array.isArray(ITEMS) || ITEMS.length === 0){
        return this.error("PC_Notify_Submit ITEMS error",ITEMS)
    }
    if(!PAYMENT_ID){
        return this.error("PC_Notify_Submit PAYMENT_ID empty");
    }
    let attachStr = ITEMS[0]['SKU_ID']||'';
    let attachArr = attachStr.split('z');
    if(attachArr.length !== 3){
        return this.error("PC_Notify_Submit SKU_ID error",attachStr);
    }




    //增加游戏服检验
    const uid=attachArr[0];
    const sid=attachArr[1];
    const id=attachArr[2];
    let api = '/order/check';
    let query = {"id":id,"uid":uid,"cyt":this.opensdk['cyt']};
    let _check_ret= await this.library("game/request",this.branch,sid,api,query);
    if(_check_ret){
        let orderModel = this.model.redis("order",this.branch);
        await orderModel.set(PAYMENT_ID,attachArr.join('|'), 600);
        return this.error("success",null);
    }
    else{
        return this.error("PC_Notify_Submit Check error");
    }

}


//PC端订单发货
function PC_Notify_Goods() {






    let payment_id = this.get("payment_id","string");
    if(!payment_id){
        return this.error("PC_Notify_Goods payment_id empty");
    }
    let result= {"orderid":payment_id};
    let orderModel = this.model.redis("order",this.branch);
    return orderModel.get(payment_id).then(attach=>{
        if(!attach){
            return Promise.reject("PC_Notify_Goods payment_id not exist",payment_id);
        }
        result['attach'] = attach;
        return pc_authorization.call(this,payment_id);
    }).then(()=>{
        //console.log('result',result)
        orderModel.del(payment_id);
        return result;
    })
}


//PC签名认证
/*
生成Base String
生成Base String的流程如下。

获取HTTP请求方法。(例子: GET)
准备从URL去除query参数后的部分。(例子:http://example.com/123456789)
由Authorization 标头获取除realm与oauth_signature外的协议参数。
由Authorization 标头获取的参数
*/
function pc_authorization(payment_id) {


    let baseString="";

    let queryParam = this.req.query;



    let Authorization = this.req.get("Authorization");
    //console.log(this.req.get("Authorization"));
    if(!Authorization){
        return this.error("Authorization empty",payment_id);
    }
    Authorization = Authorization.replace("OAuth ","");
    let dmmParam = querystring.parse(Authorization,',','=');
    for(let k in dmmParam){
        dmmParam[k] = dmmParam[k].substr(1,dmmParam[k].length-2);
    }
    let oauth_signature = dmmParam['oauth_signature'];
    delete dmmParam['realm'];
    delete dmmParam['oauth_signature'];

    //console.log('Authorization标头:',dmmParam);

  



    let keyFail=encodeURIComponent(this.opensdk.setting.key) !== dmmParam['oauth_consumer_key'];
    let keyrFail=encodeURIComponent(this.opensdk.setting.keyR) !== dmmParam['oauth_consumer_key'];
    if(keyFail&&keyrFail){
        return this.error("Authorization error-keyFail",payment_id);
    }



    // console.log('setting:',JSON.stringify(this.opensdk._id));
    // console.log('Authorization:',JSON.stringify(dmmParam));
    // console.log('oauth_signature:',oauth_signature);


    // let apiUrl = [this.req.protocol,'://',this.req.hostname,this.req.path].join('');
    // apiUrl = this.opensdk.status > 0 ? Platform[1].production : Platform[1].sandbox;
    // apiUrl = queryParam['opensocial_app_url'];


    // console.log('URL:',apiUrl);
    // console.log('request query:',JSON.stringify(this.req.query));


    // let oauthTokenSecret = null;
    // let check_signature = createSign.call(this,'GET', apiUrl, queryParam, dmmParam, oauthTokenSecret)
    // // console.log('check_signature:',check_signature)
}


//==========================================公共方法=================================================//
function createSign(httpMethod, apiUrl, queryParam, dmmParam, oauthTokenSecret,secret) {
    let baseString = createBaseString(httpMethod, apiUrl , queryParam, dmmParam)
    let arr = [encodeURIComponent(secret)];
    if(oauthTokenSecret){
        arr.push(oauthTokenSecret);
    }
    else {
        arr.push("");
    }
    let key = arr.join('&');
    // if(!oauthTokenSecret) {
    //     console.log("baseString:", baseString)
    //     console.log("secret key:", key)
    // }
    return crypto.createHmac('sha1', key).update(baseString).digest().toString('base64')
}

function createBaseString(httpMethod, apiUrl, queryParam, dmmParam) {
    let paramString = createKeyValueString(Object.assign(queryParam, dmmParam))
    //console.log(paramString)
    let c1 = encodeURIComponent(httpMethod)
    let c2 = encodeURIComponent(apiUrl)
    let c3 = encodeURIComponent(paramString)
    return `${c1}&${c2}&${c3}`
}

function createKeyValueString(params) {
    let kvStringList = []
    for (let key in params) {
        let value = params[key]
        let kvString = `${key}=${value}`
        kvStringList.push(kvString)
    }
    kvStringList.sort((a, b) => {
        return a.localeCompare(b)
    })
    return kvStringList.join("&")
}


function createAuthorization(obj) {
    let sb = `OAuth realm=""`
    for (let key in obj) {
        if (sb !== "") {
            sb += ","
        }
        let value = obj[key]
        let codeKey = encodeURIComponent(key)
        let codeValue = encodeURIComponent(value)
        sb += `${codeKey}="${codeValue}"`
    }
    return sb
}
